package com.cloudspace.yunloan;

import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.Application;
import android.app.ApplicationErrorReport;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.support.multidex.MultiDex;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;

import com.cloudspace.yunloan.config.Configs;
import com.cloudspace.yunloan.player.Utils;
import com.cloudspace.yunloan.update.UpdateInfo;
import com.cloudspace.yunloan.utils.FileUtil;
import com.cloudspace.yunloan.utils.SharedPreferencesWrapper;
import com.cloudspace.yunloan.utils.ToastMaker;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.lzy.okhttputils.OkHttpUtils;
import com.lzy.okhttputils.cache.CacheMode;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;


public class YunloanApp extends Application {
    private static final String TAG = YunloanApp.class.getSimpleName();

    public static void setApp(YunloanApp app) {
        instance = app;
    }

    public static YunloanApp getApp() {
        if (instance == null) {
            return instance = new YunloanApp();
        }
        return instance;
    }

    @Override
    public void onCreate() {
        setApp(this);
        super.onCreate();
        doOnCreate(this);

        if (findMyProcessName().equals(getPackageName())){
            initOkHttp();
        }
    }

    private static YunloanApp instance;

    public static YunloanApp getInstance() {
        return instance;
    }

    public void doOnCreate(Application app) {
        ToastMaker.init(this);
        Utils.init(this);
        pre = getSharedPreferences();
    }

    private String findMyProcessName() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> services = manager.getRunningAppProcesses();
        if (services != null) {
            for (ActivityManager.RunningAppProcessInfo process : services) {
                if (process.pid == android.os.Process.myPid()) {
                    return process.processName;
                }
            }
        }
        return "";
    }

    public SharedPreferences getSharedPreferences() {
        if (pre == null) {
            SharedPreferences sp = this.getSharedPreferences(Configs.PRE_NAME,
                    Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
            pre = new SharedPreferencesWrapper(sp);
        }
        return pre;
    }

    private Object mSpLock;

    public synchronized Object getSharedPreferenceLock() {
        if (mSpLock == null) {
            mSpLock = new Object();
        }
        return mSpLock;
    }


    private static Gson gson;

    public static Gson getGson() {
        if (gson == null) {
            return (new GsonBuilder()).create();
        }
        return gson;
    }

    private int width;
    private int height;
    private int density;

    public int getScreenWidth() {
        return width;
    }

    public static boolean isInitScreenParam = false;

    public void initScreenParams(Display display) {
        if (!isInitScreenParam) {
            isInitScreenParam = true;
            DisplayMetrics metric = new DisplayMetrics();
            display.getMetrics(metric);
            this.width = metric.widthPixels; // 屏幕宽度（像素）
            this.height = metric.heightPixels; // 屏幕高度（像素） metric.heightPixels
            // 包括信息栏
            this.density = metric.densityDpi;
        }
    }

    //运用list来保存们每一个activity是关键
    private List<AppCompatActivity> mList = new LinkedList<AppCompatActivity>();

    // add Activity
    public void addActivity(AppCompatActivity activity) {
        mList.add(activity);
    }

    public void removeActivity(AppCompatActivity activity) {
        mList.remove(activity);
    }

    public SharedPreferences pre;

    public int getScreenHeight() {
        return height;
    }

    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    private void initOkHttp() {
        //必须调用初始化
        OkHttpUtils.init(this);
        //以下都不是必须的，根据需要自行选择
        OkHttpUtils.getInstance()//
                .debug("OkHttpUtils")                                              //是否打开调试
                .setCacheMode(CacheMode.REQUEST_FAILED_READ_CACHE)
                .setConnectTimeout(OkHttpUtils.DEFAULT_MILLISECONDS)               //全局的连接超时时间
                .setReadTimeOut(OkHttpUtils.DEFAULT_MILLISECONDS)                  //全局的读取超时时间
                .setWriteTimeOut(OkHttpUtils.DEFAULT_MILLISECONDS);               //全局的写入超时时间
        //.setCookieStore(new MemoryCookieStore())                           //cookie使用内存缓存（app退出后，cookie消失）
        //.setCookieStore(new PersistentCookieStore())                       //cookie持久化存储，如果cookie不过期，则一直有效
    }


    private UpdateInfo updateInfo;

    public UpdateInfo getUpdateInfo(){
        return updateInfo;
    }

    public String getLogDir(){
        return FileUtil.getLocalLogPath();
    }

    public void forceUnregisterComponentCallbacks() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            ComponentCallbacksBehavioralAdjustmentToolIcs.INSTANCE.unregisterAll(this);
        }
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    private static class ComponentCallbacksBehavioralAdjustmentToolIcs {
        static ComponentCallbacksBehavioralAdjustmentToolIcs INSTANCE = new ComponentCallbacksBehavioralAdjustmentToolIcs();

        private WeakHashMap<ComponentCallbacks, ApplicationErrorReport.CrashInfo> mCallbacks = new WeakHashMap<>();
        private boolean mSuspended = false;

        public void onComponentCallbacksRegistered(ComponentCallbacks callback) {
            Throwable thr = new Throwable("Callback registered here.");
            ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(thr);

//            if (BuildConfig.DEBUG) Log.w(TAG, "registerComponentCallbacks: " + callback, thr);

            if (!mSuspended) {
                Log.w(TAG, "register callback:" + callback.getClass().getName());

                //com.android.org.chromium.android_webview.AwContents$AwComponentCallbacks
                if (callback.getClass().getName().startsWith("com.android.org.chromium.android_webview")) {
                    mCallbacks.put(callback, ci);
                }

                //com.google.android.gms.ads
                if (callback.getClass().getName().startsWith("com.google.android.gms.ads")) {
                    mCallbacks.put(callback, ci);
                }
                // TODO: other classes may still prove to be problematic?  For now, only watch for .gms.ads, since we know those are misbehaving
            } else {
                if (BuildConfig.DEBUG)
                    Log.e(TAG, "ComponentCallbacks was registered while tracking is suspended!");
            }
        }

        public void onComponentCallbacksUnregistered(ComponentCallbacks callback) {
            if (!mSuspended) {
                if (BuildConfig.DEBUG) {
                    Log.i(TAG, "unregisterComponentCallbacks: " + callback, new Throwable());
                }

                mCallbacks.remove(callback);
            }
        }

        public void unregisterAll(Context context) {
            mSuspended = true;

            for (Map.Entry<ComponentCallbacks, ApplicationErrorReport.CrashInfo> entry : mCallbacks.entrySet()) {
                ComponentCallbacks callback = entry.getKey();
                if (callback == null) continue;

                if (BuildConfig.DEBUG) {
                    Log.w(TAG, "Forcibly unregistering a misbehaving ComponentCallbacks: " + entry.getKey());
//                    Log.w(TAG, entry.getValue().stackTrace);
                }

                try {
                    context.unregisterComponentCallbacks(entry.getKey());
                } catch (Exception exc) {
                    if (BuildConfig.DEBUG)
                        Log.e(TAG, "Unable to unregister ComponentCallbacks", exc);
                }
            }

            mCallbacks.clear();
            mSuspended = false;
        }
    }
}
